/**
 * @file floateditctrl.h
 * @brief
 *
 * 
 *
 * @author 1823419256@qq.com
 * @version 1.0
 * @date 2011
*/

#ifndef MYBOOK_CTRLS_FLOATEDITCTRL_H_
#define MYBOOK_CTRLS_FLOATEDITCTRL_H_

#define WM_FLOAT_EDITUPDATE		(WM_USER + 601)
#define WM_FLOAT_RESIZEUPDATE	(WM_USER + 602)

class CFloatEditCtrl : public CWindowImpl<CFloatEditCtrl, CEdit>
{
public:
	typedef CWindowImpl<CFloatEditCtrl, CEdit>	baseClass;

	CFloatEditCtrl()
	{
		m_nEditData = -1;
	}

	HWND Create(HWND hWndParent, RECT& rect, int nID, DWORD dwStyle = WS_VISIBLE | WS_CHILD, LPCTSTR szWindowName = NULL)
	{
		dwStyle |= WS_BORDER | ES_AUTOHSCROLL;
		return baseClass::Create(hWndParent, rect, szWindowName, dwStyle, 0);		
	}

public:	
	BEGIN_MSG_MAP(CFloatEditCtrl)
		MESSAGE_HANDLER(WM_NCCALCSIZE, OnNcCalcSize)
		MESSAGE_HANDLER(OCM_COMMAND, OnCommand)
		MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
		MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
		MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
		MESSAGE_HANDLER(WM_FLOAT_RESIZEUPDATE, OnResizeUpdate)
	END_MSG_MAP()

	LRESULT OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{		
		LPNCCALCSIZE_PARAMS lpnccs = (LPNCCALCSIZE_PARAMS)(lParam);

		LRESULT lRes = DefWindowProc(uMsg, wParam, lParam);

		CString strText;
		int len = GetWindowTextLength() + 1;
		LPTSTR lpstr = strText.GetBufferSetLength(len + 1);
		GetWindowText(lpstr, len);
		strText.ReleaseBuffer();
		strText += _T("  ");

		HDC hdc = ::CreateCompatibleDC(NULL);
		::SelectObject(hdc, GetFont());

		SIZE size;
		::GetTextExtentPoint32(hdc, strText, strText.GetLength(), &size);

		int width = size.cx + 2 *::GetSystemMetrics(SM_CXEDGE);
		if (width > m_rcMaxWnd.Width())
			width = m_rcMaxWnd.Width();

		lpnccs->rgrc[0].right = lpnccs->rgrc[0].left + width;
		PostMessage(WM_FLOAT_RESIZEUPDATE);	

		m_rcClient = lpnccs->rgrc[0];
		m_rcClient.MoveToXY(0, 0);	

		return lRes;
	}

	LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		WORD wNotifyCode = HIWORD(wParam);

		if (wNotifyCode == EN_UPDATE)
		{
			RECT rc;
			::GetWindowRect(m_hWnd, &rc);

			int uFlags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER;
			SetWindowPos(NULL, &rc, SWP_FRAMECHANGED | uFlags);

			return 0L;
		}

		return DefWindowProc(uMsg, wParam, lParam);
	}

	LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		CPoint point(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));

		if (!m_rcClient.PtInRect(point))
		{
			::ReleaseCapture();
			SendMessage(WM_KILLFOCUS);
		}

		return 0L;
	}

	LRESULT OnKeyDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		UINT nChar = (UINT)wParam;

		if (nChar == VK_ESCAPE)
		{
			SetWindowText(_T(""));
			SendUpdateMessage();
			HideEditCtrl();
		}
		else if (nChar == VK_RETURN)
		{
			SendUpdateMessage();
			HideEditCtrl();
		}
		else
		{
			return DefWindowProc(uMsg, wParam, lParam);
		}

		return 0L;
	}

	LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		SendUpdateMessage();
		HideEditCtrl();

		return 0L;
	}

	LRESULT OnResizeUpdate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		if (IsWindowVisible())
		{
			CRect rc = m_rcMaxWnd;
			rc.right = rc.left + m_rcClient.Width();
			SetWindowPos(HWND_TOP, rc, SWP_SHOWWINDOW);
		}

		return 0L;
	}

public:
	void Show(LPRECT lpRect)
	{
		m_rcMaxWnd = lpRect;
		SetWindowPos(HWND_TOP, lpRect, SWP_SHOWWINDOW | SWP_FRAMECHANGED);
		SetSel(0, -1);
		SetFocus();

		::SetCapture(m_hWnd);
	}

	void HideEditCtrl()
	{
		SetWindowPos(NULL, &CWindow::rcDefault, SWP_HIDEWINDOW | SWP_NOMOVE);
	}

	void GetText(CString& strText)
	{
		int nLen = GetWindowTextLength() + 1;
		LPTSTR lpstr = strText.GetBufferSetLength(nLen);
		GetWindowText(lpstr, nLen);
		strText.ReleaseBuffer();
	}

	void SendUpdateMessage()
	{
		::SendMessage(GetParent(), WM_FLOAT_EDITUPDATE, 0, 0);
	}

	void SetEditData(int nData)
	{
		m_nEditData = nData;
	}

	int GetEditData() const
	{
		return m_nEditData;
	}

protected:
	CRect m_rcClient;
	CRect m_rcMaxWnd;

	int m_nEditData;
};

#endif // MYBOOK_CTRLS_FLOATEDITCTRL_H_